﻿#==============================================================================
# Theta Scripting Engine - Blink by privateer
#==============================================================================
# ► Version  : 1.2
#==============================================================================
# ► Changelog
# Ver. 1.0 | Initial release
# Ver. 1.1 | Add skill and item option
# Ver. 1.2 | Rework from scratch
#==============================================================================
# ► Introduction
# This script enables you to recreate Blink engine in your game.
# Basically, every unit is given a properties called blink counts. As long as
# an unit's blink counts isn't 0, the unit will be protected from damages. 
# But, each time the unit is protected, its blink counts will be depleted until
# it reaches 0.
#==============================================================================
# ► Instruction
# Just put this script anywhere below Scene_Debug but above Main.
#==============================================================================
# ► Compatibility
# Designed and tested for DBS. May or not work with exotic CBS and/or scripts
# that alter how a state is added/removed from an unit, how actions in battles
# are done, and how a battle is ended.
#==============================================================================
# ► Additional Informations
# * By default, units' blink counts will resetted to 0 after each battle. And,
# at the start of battle, their blink counts will be set equal to the blink 
# counts of states they have.
#==============================================================================

module TSE
  module Blink
    # Defines which states will be considered as Blink States.
    # A Blink State will add its own blink counts to its bearer.
    BLINK_STATES = {
    # State ID => Blink Counts,
    }
    
    # If true, Blink will also affect healing actions that target its bearer.
    AFFECT_HEALINGS = false
    
    # * Added Features
    # If false, Blink will only affect actions that only target its bearer. 
    AFFECT_MULTIPLE_TARGETS = false
    
    # * Added Features
    # If true, when an unit's blink counts become 0, all non-auto-states Blink
    # States will be removed.
    AUTO_REMOVE_WHEN_0 = true    
    
    # * Added Features
    # Put in any valid Weapon ID(s) that will bypass its target's protection
    # from blink.
    UNAFFECTED_WEAPONS = []
    
    # * Added Features
    # Put in any valid Skill ID(s) that will bypass its target's protection
    # from blink.
    UNAFFECTED_SKILLS = []
    
    # * Added Features
    # Put in any valid Item ID(s) that will bypass its target's protection
    # from blink.    
    UNAFFECTED_ITEMS = []
  end
end

#==============================================================================
# DON'T EDIT ANY FURTHER UNLESS YOU KNOW WHAT YOU'RE DOING!
#==============================================================================

$imported = {} if $imported.nil?
$imported["TSE-Blink"] = true

module RPG
  class State
    def blink_counts
      TSE::Blink::BLINK_STATES.has_key?(id) ? TSE::Blink::BLINK_STATES[id] : 0
    end
  end
  class Weapon
    def blink_unaffected?
      TSE::Blink::UNAFFECTED_WEAPONS.include?(id)
    end
  end
  class Skill
    def blink_unaffected?
      TSE::Blink::UNAFFECTED_SKILLS.include?(id)
    end    
  end
  class Item
    def blink_unaffected?
      TSE::Blink::UNAFFECTED_ITEMS.include?(id)
    end    
  end
end

class Game_Battler
  include TSE
  include Blink
  attr_accessor :blink_counts
  alias tse_blink_init initialize
  def initialize
    @blink_counts = 0
    tse_blink_init
  end
  
  alias tse_blink_attack_effect attack_effect
  def attack_effect(attacker)
    old_hp = self.hp
    tse_blink_attack_effect(attacker)
    # Skips if the attack damage isn't a number.
    return true unless self.damage.is_a?(Numeric)
    # Skips if the attack damage is below 0 and Blink doesn't affect healings.
    return true if self.damage < 0 and not AFFECT_HEALINGS
    # Skips if the attacker's weapon is unaffected by Blink.
    return true if attacker.is_a?(Game_Actor) and $data_weapons[attacker.weapon_id].blink_unaffected?
    if @blink_counts > 0
      self.hp = old_hp
      self.critical = false
      self.damage = "Miss"
      @blink_counts -= 1
      if @blink_counts == 0 && AUTO_REMOVE_WHEN_0
        removed = @states.find_all{|id|$data_states[id].blink_counts > 0 and 
        $data_states[id].battle_only}
        for state in removed
          remove_state(state)
        end
      end
    end
    return true
  end
  
  alias tse_blink_skill_effect skill_effect
  def skill_effect(user, skill)
    old_hp = self.hp
    tse_blink_skill_effect(user, skill)
    # Skips if skill adds Blink States.
    return true if skill.plus_state_set.any?{|id|$data_states[id].blink_counts > 0}
    # Skips if skill's damage isn't a number.
    return true unless self.damage.is_a?(Numeric)
    # Skips if skill's damage is below 0 and Blink doesn't affect healings.
    return true if self.damage < 0 and not AFFECT_HEALINGS
    # Skips if skill is unaffected by Blink.
    return true if skill.blink_unaffected?
    # Skips if skill's scopes are All Enemies or All Allies and Blink doesn't
    # affect multiple targets spells.
	  return true if [2, 4].include?(skill.scope) and not AFFECT_MULTIPLE_TARGETS
    if @blink_counts > 0
      self.hp = old_hp
      self.damage = "Miss"
      @blink_counts -= 1
      if @blink_counts == 0 && AUTO_REMOVE_WHEN_0
        removed = @states.find_all{|id|$data_states[id].blink_counts > 0 and 
        $data_states[id].battle_only}
        for state in removed
          remove_state(state)
        end
      end
    end
    return true
  end  
  
  alias tse_blink_item_effect item_effect
  def item_effect(user, item)
    old_hp = self.hp  
    tse_blink_item_effect(user, item)
    # Skips if item adds Blink States.
    return true if item.plus_state_set.any?{|id|$data_states[id].blink_counts > 0}    
    # Skips if item's damage isn't a number.
    return true unless self.damage.is_a?(Numeric)
    # Skips if item's damage is below 0 and Blink doesn't affect healings.
    return true if self.damage < 0 and not AFFECT_HEALINGS
    # Skips if item is unaffected by Blink.
    return true if item.blink_unaffected?
    # Skips if item's scopes are All Enemies or All Allies and Blink doesn't
    # affect multiple targets items.    
	  return true if [2, 4].include?(item.scope) and not AFFECT_MULTIPLE_TARGETS
    if @blink_counts > 0
      self.hp = old_hp
      self.damage = "Miss"
      @blink_counts -= 1
      if @blink_counts == 0 && AUTO_REMOVE_WHEN_0
        removed = @states.find_all{|id|$data_states[id].blink_counts > 0 and $data_states[id].battle_only}
        for state in removed
          remove_state(state)
        end
      end
    end
    return true
  end   
  
  alias tse_blink_add_state add_state
  def add_state(state_id, force = false)
    tse_blink_add_state(state_id, force = false)
    @blink_counts += $data_states[state_id].blink_counts if $game_temp.in_battle
  end
  
  alias tse_blink_remove_state remove_state
  def remove_state(state_id, force = false)
    tse_blink_remove_state(state_id, force = false)
    @blink_counts -= $data_states[state_id].blink_counts
    if @blink_counts <= 0 && AUTO_REMOVE_WHEN_0
      removed = @states.find_all{|id|$data_states[id].blink_counts > 0 and $data_states[id].battle_only}
      for state in removed
        tse_blink_remove_state(state)
      end
    end
    @blink_counts = 0 if @blink_counts < 0
  end
end

class Scene_Battle
  
  alias tse_blink_start_phase1 start_phase1
  def start_phase1
    for actor in $game_party.actors
      actor.states.each{|id|
      actor.blink_counts += $data_states[id].blink_counts}
    end
    tse_blink_start_phase1
  end
  
  alias tse_blink_start_phase5 start_phase5
  def start_phase5
    for actor in $game_party.actors
      actor.blink_counts = 0
    end
    tse_blink_start_phase5
  end
  
end
